from BaseControl import WebFindKey
from selenium.common.exceptions import MoveTargetOutOfBoundsException
from BaseView import BaseWebView, BaseWebViewDelegate, BaseWebViewDelegateBuilder, WebViewDelegateIndex
from Exeptions import ElementNotFoundException
import re


class WebTreeViewItem(BaseWebViewDelegate):
    def __init__(self, handler, index, childrenBuilder):
        super(WebTreeViewItem, self).__init__(handler, index, childrenBuilder)
        self._switcher = self.waitChildControl(WebFindKey.XPATH, "span[contains(@class,'switch')]")
        self._label = self.waitChildControl(WebFindKey.XPATH, "a[@title]")

    def children(self):
        self.expand()
        if not self.isLeaf():
            containerHandler = self.waitChildControl(WebFindKey.XPATH, "ul")
            containerIndex = WebViewDelegateIndex(self, 0)
            return self._childrenBuilder.build(containerHandler, containerIndex).children()
        return []

    def isLeaf(self):
        return "_docu" in self._switcher.get_attribute('class')

    def isSelected(self):
        return "curSelectedNode" in self._label.get_attribute('class')

    def isExpanded(self):
        if self._switcher:
            return "open" in self._switcher.get_attribute("class")
        return True

    def expand(self):
        def expandImpl(driver):
            if not self.isExpanded():
                self._switcher.click()
            return True
        self.waitFor(expandImpl, 10, "cant expand item %s" % self.tag_name, MoveTargetOutOfBoundsException)

    def setSelection(self, selection):
        def selector(driver):
            if selection:
                self._label.click()
            return selection == self.isSelected()
        self.waitFor(selector, message="can't select item %s" % self.tag_name)


class WebTreeViewCheckableItem(WebTreeViewItem):
    def __init__(self, handler, index, childrenBuilder):
        super(WebTreeViewCheckableItem, self).__init__(handler, index, childrenBuilder)
        self._checker = self.waitChildControl(WebFindKey.XPATH, "span[contains(@class, 'checkbox_')]")

    def _getCheckState(self):
        return self._checker.get_attribute('class')

    def isSelected(self):
        return "checkbox_true_full" in self._getCheckState()

    def isPartialSelected(self):
        return "checkbox_true_part" in self._getCheckState()

    def isNotSelected(self):
        return not (self.isSelected() or self.isPartialSelected())

    def setSelection(self, selection):
        selection = not selection
        def selector(driver):
            if selection != self.isNotSelected():
                self._checker.click()
            return selection == self.isNotSelected()
        self.waitFor(selector, message="can't select TreeView item %s" % self.tag_name)


class WebTreeViewDelegateBuilder(BaseWebViewDelegateBuilder):
    def __init__(self, itemCls):
        self._itemCls = itemCls

    def build(self, handler, index):
        if not index.isValid() or handler.tag_name == 'ul':
            return BaseWebViewDelegate(handler, index, self)
        return self._itemCls(handler, index, self)


class WebTreeView(BaseWebView):
    def __init__(self, handler, itemsBuilder=WebTreeViewDelegateBuilder(WebTreeViewCheckableItem)):
        super(WebTreeView, self).__init__(handler, itemsBuilder)

    def expandToPath(self, path):
        currentNode = self.rootDelegate()
        try:
            for node in re.split(r'[\\/]', path.strip('/\\')):
                if ":" in node:
                    currentNode = currentNode.childrenFor(lambda x: x.text.lower() == node.lower())[0]
                else:
                    currentNode = currentNode.childrenFor(lambda x: x.text == node)[0]
            return currentNode
        except IndexError:
            raise ElementNotFoundException("Tree item %s not found in %s" % (node, path))

    def setItemSelection(self, path, selection):
        targetItem = self.expandToPath(path)
        targetItem.setSelection(selection)
